#include <cassert>
#include <iostream>

#include "PollFilter.h"
#include "WorkManager.h"

using namespace boost::asio;
using namespace std;
using namespace tbb;


PollFilter::PollFilter(io_service &ioService, WorkManager &manager, bool showStat /* = false */)
	: filter(serial_out_of_order),
	  _ioService(ioService),
	  _manager(manager),
	  _showStat(showStat),
	  _skips(0), _totalPolled(0), _waitTime(0), _waits(0)
{
	_startTime = tick_count::now();
}

void *PollFilter::operator()(void *)
{
	WorksVector *result;

	do
	{
		size_t polled;

		if ((polled = _ioService.poll()) == 0)
		{
			tick_count waitStartTime = tick_count::now();
			_ioService.run_one(); // block here
			_waitTime += (tick_count::now() - waitStartTime).seconds();
			++_waits;

			polled = 1 + _ioService.poll();
		}

		_totalPolled += polled;

		if (_showStat)
		{
			tick_count stopTime = tick_count::now();

			if ((stopTime - _startTime).seconds() < 1)
			{	// Skip too small iterations not to slow down the filter with I/O
				++_skips;
			}
			else
			{
				double totalTime = (stopTime - _startTime).seconds();

				cout << fixed << "Waits: " << _waits << ", skips: " << _skips << ", requests: " << _totalPolled << '\n'
					 << "Time: " << totalTime * 1000 << ", waited: " << _waitTime * 1000 << ", worked: " << (totalTime - _waitTime) * 1000 << '\n'
					 << "Speed: " << _totalPolled / totalTime << " req/s, work: " << _totalPolled / (totalTime - _waitTime) << " req/s\n" << endl;

				_waitTime = _waits = _skips = _totalPolled = 0;
				_startTime = stopTime;
			}
		}
	}
	while ((result = _manager.DequeueWorks()) == NULL);

	return result;
}
